package com.jy.api.service.impl;

import com.jy.api.controller.admin.params.InventoryFlowRequest;
import com.jy.api.dao.*;
import com.jy.api.domain.*;
import com.jy.api.enums.OrderItemMakeType;
import com.jy.api.exception.MyException;
import com.jy.api.service.StockService;
import com.jy.api.service.StockTransactionService;
import com.jy.api.util.*;
import com.jy.api.wechat.service.Gzh2WxService;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Created by lihu on 2018/2/1.
 */
@Service
@Slf4j
public class StockServiceImpl implements StockService {
    @Autowired
    private StockTransactionDao stockTransactionDao;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private ProductDao productDao;
    @Autowired
    private RedisSyncLocker redisSyncLocker;
    @Autowired
    private StoreDao storeDao;
    @Autowired
    OpenNoticeDao openNoticeDao;
    @Value("${wechat.template.stock}")
    private String stock;
    @Autowired
    private Gzh2WxService gzh2WxService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ProductSalesDao productSalesDao;

    @Autowired
    private ProductMaterialDao productMaterialDao;
    @Autowired
    StockTransactionService stockTransactionService;
    @Autowired
    private MakeOrderItemDao makeOrderItemDao;
    @Autowired
    private OrderItemDao orderItemDao;
    @Autowired
    private MakeOrderDao makeOrderDao ;

    @Override
    @Transactional
    public void stockOutByOrderId(String orderId) throws Exception {
        Order order = orderDao.findOne(orderId);
        log.info("订单号{},进入方法{}", order.getId(), "stockOutByOrderId");
        long experTime = JodaUtils.getStartOfTomorrow();
        List<InventoryFlowRequest> requests = new ArrayList<>();
        HashMap<Integer, Object> map = new HashMap();
        HashMap productMap = new HashMap();
        HashMap productStockMap = new HashMap();
        HashMap<String, Object> stockMap = new HashMap();
        MakeOrder makeOrder = new MakeOrder(order);
        Store store = storeDao.findOne(order.getStoreId());
        boolean judgeMake = false;
        for (OrderItem item : order.getItems()) {
            log.info("订单号{},进入方法{}", order.getId(), "stockOutByOrderId");
            Product product = productDao.findOne(item.getProductId());
            if (product.isStockEnabled()) {
                final StockChangeTransaction lastTransaction =
                        stockTransactionDao.findByRefIdAndSkuIdAndStockLevel(orderId, product.getId(), StockLevel.BAR);
                if (lastTransaction != null) {
                    continue;
                }
            }
            if (product.isSchedulingEnabled() &&  !product.getName().contains("网费") && store.isMakeEnabled() && store.getMakeEndTime().getTime()>System.currentTimeMillis()) {
                judgeMake =true;
                String s = stringRedisTemplate.opsForValue().get(order.getStoreId() + "make");
                Integer makeCount = 88;
                if (StringUtil.isNotBlank(s)) {
                    makeCount = Integer.parseInt(s);
                }
                for (int i = 0; i < item.getQuantity(); i++) {
                    MakeOrderItem makeOrderItem = new MakeOrderItem(order, item);
                    makeOrderItem.setSpecs(item.getSpecs());
                    if (makeCount < 100) {
                        makeOrderItem.setCode("H00" + makeCount);
                    }
                    if (makeCount > 100 && makeCount < 1000) {
                        makeOrderItem.setCode("H0" + makeCount);
                    }
                    if (makeCount >= 1000) {
                        makeOrderItem.setCode("H" + makeCount);
                    }
                    makeCount+=1;
                    if (product.isMakeEnabled()) {
                        if (order.getSource().equals(OrderSource.POS)) {
                            makeOrderItem.setMakeType(OrderItemMakeType.makeIng);
                            makeOrder.setMakeType(OrderItemMakeType.makeIng);
                        } else {
                            makeOrderItem.setMakeType(OrderItemMakeType.clerkIng);
                        }
                    } else {
                       if (order.getSource().equals(OrderSource.POS)){
                           makeOrderItem.setMakeTime(new Date());
                           makeOrderItem.setMakeType(OrderItemMakeType.deliveryIng);
                       }else {
                           makeOrderItem.setMakeType(OrderItemMakeType.noMake);
                       }
                    }
                    makeOrderItem.setTableNo(order.getTableNo());
                    makeOrderItem.setDeliveryName(order.getCreatorName());
                    makeOrderItem.setTips(product.getTips());
                    makeOrder.getItems().add(makeOrderItem);
                }
                stringRedisTemplate.opsForValue().set(order.getStoreId() + "make", makeCount + "",(System.currentTimeMillis()-MyDateUtils.getStartOfToday().getTime())/1000,TimeUnit.SECONDS);

            }
            if (product.isSalesEnabled()) {
                ProductSales productSales = productSalesDao.findByProductId(product.getId());
                if (productSales!=null){
                    productSales.setCount(productSales.getCount() + product.getProductQty() * item.getQuantity());
                    productSalesDao.save(productSales);
                }

            }
            if (product.isStockEnabled()) {

                if (stockMap.containsKey(item.getProductId())) {
                    stockMap.put(product.getId(), (Integer.parseInt(stockMap.get(product.getId()).toString()) + (item.getQuantity() * product.getProductQty())));
                } else {
                    stockMap.put(product.getId(), product.getProductQty() * item.getQuantity());
                }
                productStockMap.put(product.getId(), product);
            }
            for (ProductMaterialItem productMaterialItem : product.getProductMaterialItems()) {
                if (map.containsKey(productMaterialItem.getProductMaterialId())) {
                    map.put(productMaterialItem.getProductMaterialId(), (Integer.parseInt(map.get(productMaterialItem.getProductMaterialId()).toString()) + (item.getQuantity() * productMaterialItem.getQty())));
                } else {
                    map.put(productMaterialItem.getProductMaterialId(), (item.getQuantity() * productMaterialItem.getQty()));
                }
                productMap.put(productMaterialItem.getProductMaterialId(), product.getThreshold());
            }
        }
        if (judgeMake && store.isMakeEnabled() && store.getMakeEndTime().getTime()>System.currentTimeMillis()) {
            makeOrderDao.save(makeOrder);
        }
        for (String s : stockMap.keySet()) {
            Product product = (Product) productStockMap.get(s);
            InventoryFlowRequest stockOut = new InventoryFlowRequest();
            stockOut.setSkuId(product.getId() + "");
            stockOut.setSkuName(product.getName());
            stockOut.setSkuType(1);
            stockOut.setStockLevel(StockLevel.BAR);
            stockOut.setStoreId(product.getStoreId());
            stockOut.setType(StockType.STOCK_OUT);
            stockOut.setSource(StockChangeReason.SALES_OUT);
            stockOut.setOperatorId(order.getCreatorId());
            stockOut.setOperatorName(order.getCreatorName());
            stockOut.setNotes("");
            stockOut.setMold(ProductMold.PRODUCT);
            stockOut.setRefId(orderId);
            stockOut.setQty(-Integer.parseInt(stockMap.get(s).toString()));
            String values = stringRedisTemplate.opsForValue()
                    .get(product.getId());
            if (values == null) {
                if (product.getThreshold() > 0 && product.getQuantity() - product.getThreshold() <= 0) {
                    log.info("门店{},操作{}", order.getStoreId(), "发送库存数量不足设置开始");
                    sendStock(order.getStoreId(), product.getName(), product.getQuantity(), product.getThreshold());
                    stringRedisTemplate.opsForValue().set(product.getId(), product.getId(), experTime, TimeUnit.MILLISECONDS);
                    log.info("门店{},操作{}", order.getStoreId(), "发送库存数量不足设置结束");
                }
            }
            requests.add(stockOut);
        }
        for (Integer integer : map.keySet()) {
            ProductMaterial productMaterial = productMaterialDao.findOne(integer);
            InventoryFlowRequest stockMaterialOut = new InventoryFlowRequest();
            stockMaterialOut.setSkuId(productMaterial.getId() + "");
            stockMaterialOut.setSkuName(productMaterial.getName());
            stockMaterialOut.setSkuType(2);
            stockMaterialOut.setStockLevel(StockLevel.BAR);
            stockMaterialOut.setStoreId(order.getStoreId());
            stockMaterialOut.setType(StockType.STOCK_OUT);
            stockMaterialOut.setSource(StockChangeReason.SALES_OUT);
            stockMaterialOut.setOperatorId(order.getCreatorId());
            stockMaterialOut.setOperatorName(order.getCreatorName());
            stockMaterialOut.setNotes("");
            stockMaterialOut.setRefId(orderId);
            stockMaterialOut.setMold(ProductMold.MATERIAL);
            stockMaterialOut.setQty(-Integer.parseInt(map.get(integer).toString()));
            String materialValues = stringRedisTemplate.opsForValue()
                    .get(productMaterial.getId() + "material");
            if (materialValues == null) {
                if (productMaterial.getWarnQty() > 0 && productMaterial.getStockQty() - Integer.valueOf(productMap.get(integer).toString()) <= 0) {
                    log.info("门店{},操作{}", order.getStoreId(), "发送库存数量不足设置开始");
                    sendStock(order.getStoreId(), productMaterial.getName(), productMaterial.getStockQty(), productMaterial.getWarnQty());
                    stringRedisTemplate.opsForValue().set(productMaterial.getId() + "material", productMaterial.getId() + "material", experTime, TimeUnit.MILLISECONDS);
                    log.info("门店{},操作{}", order.getStoreId(), "发送库存数量不足设置结束");
                }
            }
            requests.add(stockMaterialOut);
        }
        stockTransactionService.flows(requests);
    }

    public static void main(String[] args) {
        System.out.println((System.currentTimeMillis()-MyDateUtils.getStartOfToday().getTime())/1000);
    }
    @Async
    public void sendStock(String storeId, String productName, int qty, int threshold) {
        Store store = storeDao.findOne(storeId);
        Set<String> openids = new HashSet<>();
        List<OpenNotice> openNotices = openNoticeDao.findByStoreIdAndEnabled(store.getId(), true);
        for (OpenNotice open : openNotices) {
            openids.add(open.getOpenId());
        }
        List<WxMpTemplateData> wxMpTemplateDataList = new ArrayList<>();
        WxMpTemplateData wxMpTemplateData1 = new WxMpTemplateData("first", "您好，您有商品" + productName + "库存数量低于阈值" + threshold);
        WxMpTemplateData wxMpTemplateData2 = new WxMpTemplateData("keyword1", store.getName());
        WxMpTemplateData wxMpTemplateData3 = new WxMpTemplateData("keyword2", productName);
        WxMpTemplateData wxMpTemplateData4 = new WxMpTemplateData("keyword3", String.valueOf(qty));
        WxMpTemplateData wxMpTemplateData7 = new WxMpTemplateData("remark", "请尽快联系相关人员补充库存，感谢您的使用。");
        wxMpTemplateDataList.add(wxMpTemplateData1);
        wxMpTemplateDataList.add(wxMpTemplateData2);
        wxMpTemplateDataList.add(wxMpTemplateData3);
        wxMpTemplateDataList.add(wxMpTemplateData4);
        wxMpTemplateDataList.add(wxMpTemplateData7);
        for (String openid : openids) {
            WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                    .templateId(this.stock)
                    .toUser(openid)
                    .data(wxMpTemplateDataList)
                    .build();
            try {
                this.gzh2WxService.getTemplateMsgService().sendTemplateMsg(templateMessage);
                log.info("门店{},操作{}", storeId, "发送内容" + templateMessage);
                Thread.sleep(100);
            } catch (Exception ex) {
                log.info("sendTemplateMsg is error: {}", ex.getMessage());
            }
        }

    }
}
